package com.unswift.cloud.service.imports.system;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.cloud.adapter.logger.LoggerImportTaskAdapter;
import com.unswift.cloud.adapter.system.auth.SystemRoleAdapter;
import com.unswift.cloud.adapter.system.auth.SystemUserAccountAdapter;
import com.unswift.cloud.adapter.system.auth.SystemUserAdapter;
import com.unswift.cloud.adapter.system.auth.SystemUserRoleAdapter;
import com.unswift.cloud.adapter.system.organization.SystemDepartmentAdapter;
import com.unswift.cloud.adapter.system.organization.SystemDepartmentJobAdapter;
import com.unswift.cloud.adapter.system.organization.SystemDepartmentJobUserAdapter;
import com.unswift.cloud.adapter.system.organization.SystemDepartmentUserAdapter;
import com.unswift.cloud.adapter.system.organization.SystemJobAdapter;
import com.unswift.cloud.adapter.validate.IValidateAdapter;
import com.unswift.cloud.enums.OperatorTypeEnum;
import com.unswift.cloud.enums.imports.task.ImportTaskEventEnum;
import com.unswift.cloud.enums.system.role.AuthorityTypeEnum;
import com.unswift.cloud.imports.IImportBusinessService;
import com.unswift.cloud.pojo.bo.system.department.SystemDepartmentUserImportBo;
import com.unswift.cloud.pojo.bo.system.department.SystemDepartmentUserImportStopBo;
import com.unswift.cloud.pojo.dao.logger.imports.task.LoggerImportTaskInsertDo;
import com.unswift.cloud.pojo.dao.system.department.SystemDepartmentDataDo;
import com.unswift.cloud.pojo.dao.system.department.job.SystemDepartmentJobDataDo;
import com.unswift.cloud.pojo.dao.system.department.job.user.SystemDepartmentJobUserInsertDo;
import com.unswift.cloud.pojo.dao.system.department.user.SystemDepartmentUserInsertDo;
import com.unswift.cloud.pojo.dao.system.job.SystemJobDataDo;
import com.unswift.cloud.pojo.dao.system.role.SystemRoleDataDo;
import com.unswift.cloud.pojo.dao.system.user.SystemUserInsertDo;
import com.unswift.cloud.pojo.dao.system.user.account.SystemUserAccountInsertDo;
import com.unswift.cloud.pojo.dao.system.user.role.SystemUserRoleInsertBatchDo;
import com.unswift.cloud.pojo.dao.system.user.role.SystemUserRoleInsertBatchItemDo;
import com.unswift.cloud.pojo.mo.system.department.SystemDepartmentUserImportMo;
import com.unswift.cloud.pojo.mso.logger.imports.task.LoggerImportTaskQueueMso;
import com.unswift.cloud.pojo.vo.system.department.SystemDepartmentUserImportStopVo;
import com.unswift.cloud.pojo.vo.system.department.SystemDepartmentUserImportVo;
import com.unswift.cloud.rabbit.RabbitConstant;
import com.unswift.cloud.rabbit.RabbitQueue;
import com.unswift.cloud.service.BaseService;
import com.unswift.cloud.service.LoggerService;
import com.unswift.utils.EncryptionUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.JsonUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.utils.StringUtils;

@Service
public class SystemDepartmentUserImportService extends BaseService implements IImportBusinessService<SystemDepartmentUserImportMo, SystemDepartmentUserImportBo>, RabbitConstant{

	@Autowired
	@ApiField("用户公共服务")
	private SystemUserAdapter systemUserAdapter;
	
	@Autowired
	@ApiField("导入公共服务")
	private LoggerImportTaskAdapter loggerImportTaskAdapter;
	
	@Autowired
	@ApiField("用户账号公共服务")
	private SystemUserAccountAdapter systemUserAccountAdapter;
	
	@Autowired
	@ApiField("角色公共服务")
	private SystemRoleAdapter systemRoleAdapter;
	
	@Autowired
	@ApiField("部门用户账号公共服务")
	private SystemUserRoleAdapter systemUserRoleAdapter;
	
	@Autowired
	@ApiField("职位公共服务")
	private SystemJobAdapter systemJobAdapter;
	
	@Autowired
	@ApiField("部门公共服务")
	private SystemDepartmentAdapter systemDepartmentAdapter;
	
	@Autowired
	@ApiField("部门职位公共服务")
	private SystemDepartmentJobAdapter systemDepartmentJobAdapter;
	
	@Autowired
	@ApiField("部门用户公共服务")
	private SystemDepartmentUserAdapter systemDepartmentUserAdapter;
	
	@Autowired
	@ApiField("部门职位用户公共服务")
	private SystemDepartmentJobUserAdapter systemDepartmentJobUserAdapter;
	
	@Autowired
	@ApiField("操作日志服务")
	private LoggerService loggerService;
	
	@Autowired
	@ApiField("Rabbit Mq发送消息服务")
	private RabbitQueue rabbitQueue;
	
	@Autowired
	@ApiField("表单验证公共操作")
	private IValidateAdapter validateAdapter;
	
	@ApiMethod(value="导入部门用户(不要加事务，否则有可能导致任务还没创建，但是队列已经消费查询，最终导致导入报错)", params=@ApiField("导入业务实体，包含附件信息"), returns=@ApiField("导入结果Vo->result:{0：未被导入，1：已成功导入}"))
	public SystemDepartmentUserImportVo imports(SystemDepartmentUserImportBo importBo) {
		ExceptionUtils.trueException(loggerImportTaskAdapter.existsTasking(this.getUserId(), systemUserAdapter.getModule()), "task.is.currently.executing", "有部门用户导入");
		Date date=new Date();
		LoggerImportTaskInsertDo task=new LoggerImportTaskInsertDo();
		task.setName("部门用户");
		task.setModule(systemUserAdapter.getModule());
		task.setDocumentType("excel");
		task.setStatus((byte)0);
		task.setStartTime(date);
		task.setImportBeanClass(this.getClass().getName());
		task.setImportModelClass(SystemDepartmentUserImportBo.class.getName());
		task.setImportData(JsonUtils.toJson(importBo));
		task.setResult((byte)0);
		task.setProgress(new BigDecimal(10));
		int result=loggerImportTaskAdapter.save(task, false);//保存任务，不用加事务，防止队列消费的时候还没保存完数据
		rabbitQueue.sendMessage(IMPORT_EXCHANGE_NAME, IMPORT_ROUTE_KEY, new LoggerImportTaskQueueMso(task.getId(), ImportTaskEventEnum.START, this.getHeader(tokenConfig.getKeyName()), getLanguage()));//发送导出队列
		return new SystemDepartmentUserImportVo(task.getId(), result);
	}
	
	@ApiMethod(value="停止导入部门用户", params=@ApiField("停止导入对象"))
	public SystemDepartmentUserImportStopVo stop(SystemDepartmentUserImportStopBo importStopBo){
		rabbitQueue.sendMessage(IMPORT_STOP_EXCHANGE_NAME, IMPORT_STOP_ROUTE_KEY, new LoggerImportTaskQueueMso(importStopBo.getId(), ImportTaskEventEnum.STOP, this.getHeader(tokenConfig.getKeyName()), getLanguage()));//发送停止导入队列
		return new SystemDepartmentUserImportStopVo(1);
	}

	@Override
	@ApiMethod(value="获取导出模板的类类型", returns=@ApiField("导出模板类类型"))
	public Class<SystemDepartmentUserImportMo> getModule() {
		return SystemDepartmentUserImportMo.class;
	}
	
	@Override
	@ApiMethod(value="导入开始时执行")
	public void start() {
		validateAdapter.setAttribute("accountDb", systemUserAccountAdapter);//设置账号公共操作变量，保证在验证对象中可查询数据字典类型相关的业务
		validateAdapter.setAttribute("roleDb", systemRoleAdapter);//设置角色公共操作变量，保证在验证对象中可查询语言相关的业务
	}
	
	@Override
	@ApiMethod(value="导入行数据验证，请再此处处理完所有的验证，否则可能导致数据导入一部分", params = {@ApiField("需验证的行数据"), @ApiField("此数据在excel中的行次（从零开始）"), @ApiField("操作导出的用户token"), @ApiField("导入条件")})
	public void validate(SystemDepartmentUserImportMo rowData, int rowIndex, String token, SystemDepartmentUserImportBo condition) {
		rowData.setRowNumber(rowIndex+1);
		rowData.setRoleNameArray(rowData.getRoleNames().split("[,，]"));
		validateAdapter.validate(systemUserAdapter.getModule(), "import", rowData, this.getUser(token), systemUserAdapter);//验证表单
		
		String jobNames = rowData.getJobNames();
		if(ObjectUtils.isNotEmpty(jobNames)) {
			SystemDepartmentDataDo department=systemDepartmentAdapter.findById(condition.getDepartmentId());
			ExceptionUtils.empty(department, "row.object.cannot.found", "部门", condition.getDepartmentId(), rowIndex+1);
			String[] jobArray=jobNames.split("[,，]");
			for (String jobName : jobArray) {
				SystemJobDataDo job = systemJobAdapter.findByName(jobName);
				ExceptionUtils.empty(job, "row.object.cannot.found", "职位", jobName, rowIndex+1);
				SystemDepartmentJobDataDo departmentJob = systemDepartmentJobAdapter.findByCode(department.getCode(), job.getCode());
				ExceptionUtils.empty(departmentJob, "row.objects.not.exists", String.format("部门（%s），职位（%s）", department.getName(), job.getName()), rowIndex);
			}
		}
	}

	@Override
	@Transactional("systemTransactionManager")
	@ApiMethod(value="导入数据批量处理，批次数据根据nocos配置确定批次大小", params = {@ApiField("批次数据"), @ApiField("此列表在excel中的开始行次（从零开始）"), @ApiField("操作导出的用户token"), @ApiField("导入条件")})
	public void handleBatch(List<SystemDepartmentUserImportMo> rowList, int startRowIndex, String token, SystemDepartmentUserImportBo condition) {
		Long userId=this.getUserId(token);
		SystemUserRoleInsertBatchItemDo userRoleInsert;
		List<SystemUserRoleInsertBatchItemDo> userRoleInsertList;
		SystemUserInsertDo insertUser;
		String[] roleArray;
		Map<String, Long> roleMap=new HashMap<String, Long>();
		SystemDepartmentUserInsertDo insertDepartmentUser;
		SystemDepartmentJobUserInsertDo insertDepartmentJobUser;
		for (SystemDepartmentUserImportMo importData : rowList) {
			insertUser=new SystemUserInsertDo();
			ObjectUtils.copy(importData, insertUser);
			if(ObjectUtils.isNotEmpty(importData.getIdCardTypeName())){
				insertUser.setIdCardType(Integer.parseInt(cacheAdapter.findDictionaryKeyByValue("idCardType", importData.getIdCardTypeName())));
			}
			if(ObjectUtils.isNotEmpty(importData.getIdCardShow())) {
				insertUser.setIdCard(EncryptionUtils.md5Hex(importData.getIdCardShow()));
				insertUser.setIdCardShow(StringUtils.hiddenCenter(importData.getIdCardShow(), 4, 3));
			}
			if(ObjectUtils.isNotEmpty(insertUser.getSex())){
				insertUser.setSex(cacheAdapter.findDictionaryKeyByValue("sex", insertUser.getSex()));
			}
			insertUser.setPassword(EncryptionUtils.md5Hex(insertUser.getPassword()));
			insertUser.setCreateUser(userId);
			insertUser.setChangeUser(userId);
			systemUserAdapter.save(insertUser, true);
			roleArray=importData.getRoleNames().split("[,，]");
			userRoleInsertList=new ArrayList<SystemUserRoleInsertBatchItemDo>();
			for (String roleName : roleArray) {
				if(!roleMap.containsKey(roleName)) {
					SystemRoleDataDo role = systemRoleAdapter.findByName(roleName);
					ExceptionUtils.empty(role, "object.already.exists", "角色", roleName);
					roleMap.put(roleName, role.getId());
				}
				userRoleInsert=new SystemUserRoleInsertBatchItemDo();
				userRoleInsert.setUserId(insertUser.getId());
				userRoleInsert.setRoleId(roleMap.get(roleName));
				userRoleInsert.setAuthorityType(AuthorityTypeEnum.OCCUPANT.getKey());
				userRoleInsert.setCreateUser(userId);
				userRoleInsert.setChangeUser(userId);
				userRoleInsertList.add(userRoleInsert);
			}
			systemUserRoleAdapter.saveBatch(new SystemUserRoleInsertBatchDo(userRoleInsertList), false);
			SystemUserAccountInsertDo account = new SystemUserAccountInsertDo(insertUser.getId(), importData.getAccount(), "no");
			account.setCreateUser(userId);
			account.setChangeUser(userId);
			systemUserAccountAdapter.save(account, false);
			if(ObjectUtils.isNotEmpty(importData.getPhone())) {
				account=new SystemUserAccountInsertDo(insertUser.getId(), importData.getPhone(), "phone");
				account.setCreateUser(userId);
				account.setChangeUser(userId);
				systemUserAccountAdapter.save(account, false);
			}
			if(ObjectUtils.isNotEmpty(importData.getEmail())) {
				account=new SystemUserAccountInsertDo(insertUser.getId(), importData.getEmail(), "email");
				account.setCreateUser(userId);
				account.setChangeUser(userId);
				systemUserAccountAdapter.save(account, false);
			}
			SystemDepartmentDataDo department=systemDepartmentAdapter.findById(condition.getDepartmentId());
			insertDepartmentUser=new SystemDepartmentUserInsertDo();
			insertDepartmentUser.setUserId(insertUser.getId());
			insertDepartmentUser.setDepartmentId(department.getId());
			insertDepartmentUser.setSort(1);
			insertDepartmentUser.setCreateUser(userId);
			insertDepartmentUser.setChangeUser(userId);
			systemDepartmentUserAdapter.save(insertDepartmentUser, false);
			
			String jobNames = importData.getJobNames();
			if(ObjectUtils.isNotEmpty(jobNames)) {
				String[] jobArray=jobNames.split("[,，]");
				int sort=1;
				for (String jobName : jobArray) {
					SystemJobDataDo job = systemJobAdapter.findByName(jobName);
					SystemDepartmentJobDataDo departmentJob = systemDepartmentJobAdapter.findByCode(department.getCode(), job.getCode());
					insertDepartmentJobUser=new SystemDepartmentJobUserInsertDo();
					insertDepartmentJobUser.setDepartmentJobId(departmentJob.getId());
					insertDepartmentJobUser.setDepartmentUserId(insertDepartmentUser.getId());
					insertDepartmentJobUser.setSort(sort);
					insertDepartmentJobUser.setCreateUser(userId);
					insertDepartmentJobUser.setChangeUser(userId);
					systemDepartmentJobUserAdapter.save(insertDepartmentJobUser, false);
					sort++;
				}
			}
			loggerService.writer(insertUser.getId(), systemUserAdapter.getModule(), OperatorTypeEnum.IMPORT, token, importData);
		}
	}
	
	@Override
	@ApiMethod(value="结束导入时触发，如清理临时缓存等", params = {@ApiField("用户token")})
	public void finish(String token) {
		validateAdapter.finish();
	}
}
